package cn.iocoder.yudao.module.engine.service.core.filter.read;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.engine.enums.EnumAudioType;
import cn.iocoder.yudao.module.engine.model.context.ControlEngineContext;
import cn.iocoder.yudao.module.engine.model.engine.EngineOutputData;
import cn.iocoder.yudao.module.engine.service.core.pipeline.FilterAdapter;
import cn.iocoder.yudao.module.engine.service.core.pipeline.FilterContext;
import cn.iocoder.yudao.module.engine.service.log.IEngineLogService;
import cn.iocoder.yudao.module.engine.util.AudioUtils;
import cn.iocoder.yudao.module.engine.util.EngineConvertUtils;
import cn.iocoder.yudao.module.resource.api.IAudioCommandApi;
import cn.iocoder.yudao.module.resource.api.IAudioServiceApi;
import cn.iocoder.yudao.module.resource.api.enums.MessageSourceTypeEnum;
import cn.iocoder.yudao.module.resource.api.model.AudioCommandDTO;
import cn.iocoder.yudao.module.resource.api.model.AudioDTO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 根据语音文本中的关键字，执行传感器指令
 */
@Slf4j
@Component
public class Keyword2SensorInstructionFilter extends FilterAdapter {
    @Resource
    private IAudioCommandApi audioCommandApi;
    @Resource
    private IEngineLogService logService;
    @Resource
    private IAudioServiceApi audioApi;

    @Override
    public void read(FilterContext ctx, ControlEngineContext engineContext) throws Exception {
        final String userText = engineContext.getUserText();
        if (StrUtil.isEmpty(userText)) {
            ctx.fireRead(engineContext);
            return;
        }

        final List<String> matchedWords = audioCommandApi.matchedWords(userText);
        final boolean contains = CollUtil.isNotEmpty(matchedWords);
        log.info("检测是否包含控制指令, contains = {}, userText = {}, matchedWords = {}",
                contains, userText, matchedWords);
        if (!contains) {
            ctx.fireRead(engineContext);
            return;
        }

        final Map<String, AudioCommandDTO> word2Command = audioCommandApi.getWord2Command();
        final String maxPriorityWord = getMaxPriorityWord(matchedWords, word2Command);
        final AudioCommandDTO cmd = word2Command.get(maxPriorityWord);

        final String sensorType = cmd.getSensorType();
        final String operationType = cmd.getOperateType();
        log.info("触发控制指令, maxPriorityWord = {}, sensorType = {}, operationType = {}, durationSec = {}, step = {}",
                maxPriorityWord, sensorType, operationType, cmd.getDurationSec(), cmd.getStep());

        logService.log(engineContext, StrUtil.format("【触发控制指令】 [指令名]: {}, [指令值]: {}, [持续时间]: {}, [触发关键字]: {}",
                cmd.getCmdTitle(), cmd.getStep(), cmd.getDurationSec(), maxPriorityWord));

        final EngineOutputData.SensorInstruction instruction = EngineOutputData.SensorInstruction.builder()
                .sensorType(sensorType)
                .operationType(operationType)
                .step(cmd.getStep() != null ? cmd.getStep().stripTrailingZeros() : null)
                .durationSec(cmd.getDurationSec())
                .extension(cmd.getExtension())
                .build();
        engineContext.getOutputData().getSensorInstructions().add(instruction);

        final String audioTags = cmd.getAudioTags();
        if (StrUtil.isNotBlank(audioTags)) {
            final AudioDTO audioDto = queryFeedbackAudioByTags(engineContext, audioTags);
            if (audioDto != null) {
                final EngineOutputData.Audio feedbackAudio = EngineConvertUtils.toEngineOutputData(
                        engineContext.getUserText(), engineContext.getChatId(),
                        MessageSourceTypeEnum.SYSTEM, EnumAudioType.CMD_AUDIO, audioDto);
                instruction.setFeedbackAudio(feedbackAudio);
            }
        }

        ctx.fireRead(engineContext);
    }

    private AudioDTO queryFeedbackAudioByTags(ControlEngineContext engineContext, String audioTags) {
        final List<String> queryTags = new ArrayList<>();
        final String[] split = audioTags.split("\\|");
        for (String str : split) {
            if (StringUtils.isNotBlank(str)) {
                queryTags.add(StringUtils.trim(str));
            }
        }

        if (CollUtil.isEmpty(queryTags)) {
            log.warn("audioTags为空, audioTags = {}", audioTags);
            return null;
        }

        final List<AudioDTO> audios = audioApi.queryAudioByTag(engineContext.getRoleId(), queryTags);
        log.info("查询指令对应的反馈音频, audiosSize = {}", audios.size());
        if (CollUtil.isEmpty(audios)) {
            return null;
        }

        final AudioDTO audioDto = AudioUtils.randomAudio(engineContext.getSessionCtx(), audios);
        log.info("随机指令对应的反馈音频: {}", JsonUtils.toJsonString(audioDto));
        return audioDto;
    }

    private static String getMaxPriorityWord(List<String> matchedWords, Map<String, AudioCommandDTO> word2Command) {
        String maxPriorityWord = null;
        if (matchedWords.size() > 1) {
            // 如果matchedWords有多个，找出优先级最高的word
            for (String word : matchedWords) {
                if (maxPriorityWord == null) {
                    maxPriorityWord = word;
                } else {
                    if (word2Command.get(word).getPriority() < word2Command.get(maxPriorityWord).getPriority()) {
                        maxPriorityWord = word;
                    }
                }
            }
        } else {
            maxPriorityWord = matchedWords.get(0);
        }
        return maxPriorityWord;
    }

}
